package com.shanshan.system.config;

import com.alibaba.fastjson.JSON;
import com.shanshan.system.filter.MySecuityFilter;
import com.shanshan.system.service.LoginService;
import com.shanshan.system.util.JwtUtil;
import kotlin.Result;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
@SuppressWarnings("all")
public class MyVueSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginService userService;

    @Autowired
    private MySecuityFilter filter;

    /**
     * 创建密码编码器
     *
     * @return {@link PasswordEncoder}
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**
     * 指定账户和密码的来源
     *
     * @param auth 身份验证
     * @throws Exception 异常
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 注入自己写的过滤器在安全认证框架前
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
        // 设置其他路径需要登录认证后才进行访问
        http.authorizeRequests()
                // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                .antMatchers("/login", "/captchaImage","/upload/sure").permitAll()
                // 静态资源，可匿名访问
                .antMatchers("/notice/list","/system/news/newkind1", "/system/news/newkind2","/echarts/record",
                        "/system/news/newkind1ById","/system/news/newkind2ById","/system/branch/list",
                        "/system/branch/listId","/system/admin/branchId","/system/admin/selectId",
                        "/system/admin/accountName","/system/record/addRecord","/system/meetingClass/updateUsed",
                        "/echarts/getBranch","/system/record/list","/excel/download").permitAll()
                //.antMatchers("/").permitAll()
                //其它所有请求都需要进行验证
                .anyRequest().authenticated();
        // 放行登录表单资源
        http.formLogin()
                // 设置登录成功后的路径。该路径是接口路径，那么提交方式必须为post
                .loginProcessingUrl("/login")
                // 登录成功后转发的路径
                .successHandler(successHandler())
                // 登录失败后转发的路径
                .failureHandler(failureHandler())
                .permitAll();

        // 没有权限跳转路径
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());

        //禁用跨站伪造请求,不使用csrf过滤器。 允许跨域 cors
        http.csrf().disable().cors();


    }

    private AccessDeniedHandler accessDeniedHandler() {
        return (request, response, authentication) ->{
            response.setContentType("json/application;charset=utf-8");
            com.shanshan.system.vo.Result result = new com.shanshan.system.vo.Result(200, "登陆成功");
            String s = JSON.toJSONString(result);
            PrintWriter writer = response.getWriter();
            writer.print(s);

            writer.flush();
            writer.close();
        };
    }

    private AuthenticationFailureHandler failureHandler() {
        return (request, response, authentication) ->{
            response.setContentType("json/application;charset=utf-8");
            com.shanshan.system.vo.Result result = new com.shanshan.system.vo.Result(500, "登录失败,账户或密码错误");
            String s = JSON.toJSONString(result);
            PrintWriter writer = response.getWriter();
            writer.print(s);

            writer.flush();
            writer.close();
        };
    }

    public AuthenticationSuccessHandler successHandler() {
        // 使用匿名内部类
        return new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                response.setContentType("json/application;charset=utf-8");
                //登录成功的业务代码--servlet可以通过对象传输json对象
                User principal = (User) authentication.getPrincipal();
                String username = principal.getUsername();
                // 获取用户所拥有的权限并处理为 List<String> 类型

                List<String> collect = principal.getAuthorities()
                        .stream().map(GrantedAuthority::getAuthority)
                        .collect(Collectors.toList());

                HashMap<String, Object> map = new HashMap<>();
                map.put("username",username);
                map.put("permission",collect);

                String token = JwtUtil.createToken(map);

                com.shanshan.system.vo.Result result = new com.shanshan.system.vo.Result(200,"登录成功",token);
                String jsonString = JSON.toJSONString(result);
                PrintWriter writer = response.getWriter();
                writer.print(jsonString);

                writer.flush();
                writer.close();
            }
        };
//        return (request, response, authentication) ->{};
    }
}